package EstimatorPackage;

import ClassAlgebra.Expression;
import ClassAlgebra.ProbAlgebraSingleton;
import ClassAlgebra.ProbExpr;
import ClassAlgebra.SimpleProbExpr;
import HierarchyPackage.Hierarchy;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 *
 * @author Martin Haulrich
 */
public abstract class AbstractEstimatorExp implements EstimatorExp {

    Map<Expression, ProbExpr> cache;

    final int csize;


    public AbstractEstimatorExp() {
        csize = 0;
    }


    public AbstractEstimatorExp(int cacheSize) {
        csize = cacheSize;
        cache = new LinkedHashMap<Expression, ProbExpr>(cacheSize, 0.75F, true) {

            @Override
            protected boolean removeEldestEntry(Map.Entry<Expression, ProbExpr> eldest) {
                return size() > (csize * 0.8);
            }
        };

    }


    @Override
    public double getEstimate(Expression pe) {
        //   System.err.println("hej");
        // We convert the ecpression to a probability-expression and use ProbAlgebra to try and reduce it

        ProbExpr npe;
        if (csize != 0) {
            npe = cache.get(pe);
            if (npe == null) {
              //  npe = ProbAlgebra.map(new SimpleProbExpr(pe));
                npe = ProbAlgebraSingleton.getInstance().map(new SimpleProbExpr(pe));
                cache.put(pe, npe);
            }
        } else {
            //npe = ProbAlgebra.map(new SimpleProbExpr(pe));
            npe = ProbAlgebraSingleton.getInstance().map(new SimpleProbExpr(pe));
        }
        //ProbExpr npe = ProbAlgebra.map(new SimpleProbExpr(pe));

        //    System.err.println("Mapped " + pe + " to " + npe);
        return getEstimateRec(npe);


    }


    @Override
    public double getEstimate(Expression pe, Hierarchy hier) {
        //     System.err.println("hej");
        // We convert the ecpression to a probability-expression and use ProbAlgebra to try and reduce it
        //     ProbExpr npe = ProbAlgebra.map(new SimpleProbExpr(pe), hier);
        ProbExpr npe;
       // System.out.println("suf-called");
        if (csize != 0) {
            npe = cache.get(pe);
            if (npe == null) {
                //npe = ProbAlgebra.map(new SimpleProbExpr(pe), hier);
                npe = ProbAlgebraSingleton.getInstance().map(new SimpleProbExpr(pe), hier);
                cache.put(pe, npe);
            }
//            else {
//                System.out.println("suf-hit");
//            }
        } else {
            //npe = ProbAlgebra.map(new SimpleProbExpr(pe), hier);
            npe = ProbAlgebraSingleton.getInstance().map(new SimpleProbExpr(pe), hier);
        }
        //   System.err.println("Mapped " + pe + " to " + npe);
        return getEstimateRec(npe);

    }


    public abstract double getEstimateRec(ProbExpr pe);
}
